 precision highp float;

  uniform samplerCube cubemap;
  uniform sampler2D noise;
  uniform sampler2D permTexture;
  uniform sampler2D gradTexture;
  uniform float time; // Used for texture animation

  varying vec3 vTextureCoord;
  varying vec3 vTransformedNormal;
  varying vec4 vPosition;
  varying vec3 vViewVec;
  varying vec3 vNormal;
  
    uniform float uMaterialShininess;

    uniform vec3 uAmbientColor;

    uniform vec3 uPointLightingLocation;
    uniform vec3 uPointLightingSpecularColor;
    uniform vec3 uPointLightingDiffuseColor;
  /*
   * To create offsets of one texel and one half texel in the
   * texture lookup, we need to know the texture image size.
   */
  #define ONE 0.00390625
  #define ONEHALF 0.001953125
  // The numbers above are 1/256 and 0.5/256, change accordingly
  // if you change the code to use another perm/grad texture size.

  void simplex(const in vec4 P, out vec4 offset1, out vec4 offset2, out vec4 offset3) {
    vec4 offset0;
 
    vec3 isX = step( P.yzw, P.xxx );       
    offset0.x = dot( isX, vec3( 1.0 ) );
    offset0.yzw = 1.0 - isX;

    vec2 isY = step( P.zw, P.yy );
    offset0.y += dot( isY, vec2( 1.0 ) );
    offset0.zw += 1.0 - isY;
 
    float isZ = step( P.w, P.z );
    offset0.z += isZ;
    offset0.w += 1.0 - isZ;
        
    offset3 = clamp(   offset0, 0.0, 1.0 );
    offset2 = clamp( --offset0, 0.0, 1.0 );
    offset1 = clamp( --offset0, 0.0, 1.0 );
  }
  
 /*
  * 4D simplex noise. A lot faster than classic 4D noise, and better looking.
  */

  float snoise(const in vec4 P) {

    // The skewing and unskewing factors are hairy again for the 4D case
    // This is (sqrt(5.0)-1.0)/4.0
    #define F4 0.309016994375
    // This is (5.0-sqrt(5.0))/20.0
    #define G4 0.138196601125

    // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
    float s = (P.x + P.y + P.z + P.w) * F4; // Factor for 4D skewing
    vec4 Pi = floor(P + s);
    float t = (Pi.x + Pi.y + Pi.z + Pi.w) * G4;
    vec4 P0 = Pi - t; // Unskew the cell origin back to (x,y,z,w) space
    Pi = Pi * ONE + ONEHALF; // Integer part, scaled and offset for texture lookup

    vec4 Pf0 = P - P0;  // The x,y distances from the cell origin

    vec4 o1;
    vec4 o2;
    vec4 o3;
    simplex(Pf0, o1, o2, o3);  

    // Noise contribution from simplex origin
    float perm0xy = texture2D(permTexture, Pi.xy).a;
    float perm0zw = texture2D(permTexture, Pi.zw).a;
    vec4  grad0 = texture2D(gradTexture, vec2(perm0xy, perm0zw)).rgba * 5.0 - 1.0;
    float t0 = 0.6 - dot(Pf0, Pf0);
    float n0;
    if (t0 < 0.0) n0 = 0.0;
    else {
      t0 *= t0;
      n0 = t0 * t0 * dot(grad0, Pf0);
    }

    // Noise contribution from second corner
    vec4 Pf1 = Pf0 - o1 + G4;
    o1 = o1 * ONE;
    float perm1xy = texture2D(permTexture, Pi.xy + o1.xy).a;
    float perm1zw = texture2D(permTexture, Pi.zw + o1.zw).a;
    vec4  grad1 = texture2D(gradTexture, vec2(perm1xy, perm1zw)).rgba * 5.0 - 1.0;
    float t1 = 0.6 - dot(Pf1, Pf1);
    float n1;
    if (t1 < 0.0) n1 = 0.0;
    else {
      t1 *= t1;
      n1 = t1 * t1 * dot(grad1, Pf1);
    }
  
    // Noise contribution from third corner
    vec4 Pf2 = Pf0 - o2 + 2.0 * G4;
    o2 = o2 * ONE;
    float perm2xy = texture2D(permTexture, Pi.xy + o2.xy).a;
    float perm2zw = texture2D(permTexture, Pi.zw + o2.zw).a;
    vec4  grad2 = texture2D(gradTexture, vec2(perm2xy, perm2zw)).rgba * 5.0 - 1.0;
    float t2 = 0.6 - dot(Pf2, Pf2);
    float n2;
    if (t2 < 0.0) n2 = 0.0;
    else {
      t2 *= t2;
      n2 = t2 * t2 * dot(grad2, Pf2);
    }
  
    // Noise contribution from fourth corner
    vec4 Pf3 = Pf0 - o3 + 3.0 * G4;
    o3 = o3 * ONE;
    float perm3xy = texture2D(permTexture, Pi.xy + o3.xy).a;
    float perm3zw = texture2D(permTexture, Pi.zw + o3.zw).a;
    vec4  grad3 = texture2D(gradTexture, vec2(perm3xy, perm3zw)).rgba * 5.0 - 1.0;
    float t3 = 0.6 - dot(Pf3, Pf3);
    float n3;
    if (t3 < 0.0) n3 = 0.0;
    else {
      t3 *= t3;
      n3 = t3 * t3 * dot(grad3, Pf3);
    }
  
    // Noise contribution from last corner
    vec4 Pf4 = Pf0 - vec4(1.0-4.0*G4);
    float perm4xy = texture2D(permTexture, Pi.xy + vec2(ONE, ONE)).a;
    float perm4zw = texture2D(permTexture, Pi.zw + vec2(ONE, ONE)).a;
    vec4  grad4 = texture2D(gradTexture, vec2(perm4xy, perm4zw)).rgba * 5.0 - 1.0;
    float t4 = 0.6 - dot(Pf4, Pf4);
    float n4;
    if(t4 < 0.0) n4 = 0.0;
    else {
      t4 *= t4;
      n4 = t4 * t4 * dot(grad4, Pf4);
    }

    // Sum up and scale the result to cover the range [-1,1]
    return 27.0 * (n0 + n1 + n2 + n3 + n4);
  }

  // Ridged multifractal
  float ridge(float h, float offset) {
    h = abs(h);
    h = offset - h;
    h = h * h;
    return h;
  }

  float ridgedmf(vec4 p, float lacunarity, float gain, float offset, int octaves) {
        float sum = 0.0;
        float freq = 2.5, amp = 0.1;
        float prev = 2.0;
        for(int i=0; i<3; i++) {
          float noise = snoise(p*freq);
      float n = ridge(noise, offset);
          sum += n*amp*prev;
          prev = n;
          freq *= lacunarity;
          amp *= gain;
        }
        return sum;
  }

  float ridgedmfDefault(vec4 p, int octaves) {
    return ridgedmf(p, 3.0, 1.8, 1.0, octaves);
  }

  void main(void) {
    float red = ridgedmfDefault(vec4(vTextureCoord.xyz*0.0052525, time / 85.0), 2);
    float green = ridgedmfDefault(vec4(vTextureCoord.xyz*0.0052525,time / 85.0), 2);
    float blue = ridgedmfDefault(vec4(vTextureCoord.xyz*0.0052525, time / 85.0), 2);
	
	vec3 lightWeighting;
	vec3 lightDirection = normalize(uPointLightingLocation - vPosition.xyz);
	vec3 normal = normalize(vTransformedNormal);
	
	float specularLightWeighting = 0.0;
		vec3 eyeDirection = normalize(-vPosition.xyz);
		vec3 reflectionDirection = reflect(-lightDirection, normal);

		specularLightWeighting = pow(max(dot(reflectionDirection, eyeDirection), 0.0), uMaterialShininess);
		
		float diffuseLightWeighting = max(dot(normal, lightDirection), 0.0);
		lightWeighting = uAmbientColor
			+ uPointLightingSpecularColor * specularLightWeighting
			+ uPointLightingDiffuseColor * diffuseLightWeighting;
			
	vec3 tcoord = vTextureCoord;
	tcoord.x += 0.2 + cos(time) * 0.5;
	tcoord.y += 0.2 + time;
	
	vec4 noisy = texture2DProj(noise, vPosition.xzy);
	vec3 bump = 0.2 * noisy.xzy - 1.0;
	bump.y = 0.8 * abs(bump.y) + 0.2;
	bump.xz *= 0.015;
	
	bump =  normalize(vNormal.xyz - bump.xyz)/(vViewVec*0.5);
	vec3 reflVec = reflect(vViewVec*0.5, bump) ;

	vec4 refl = textureCube(cubemap, reflVec.xyz);
	float lrp = 1.0 - (dot (normalize(vViewVec), bump)) ;
	


    vec4 color = vec4(0.0, green,green*1.2, 1);//vec4(color.rgb * lightWeighting, color.a)
    color = vec4(color.rgb * lightWeighting, color.a);
    color.gb /= abs(sin(vPosition.y*0.825)*cos(vPosition.y*0.825))*2.925;

	gl_FragColor =  mix( color*2.0,refl, clamp(0.25+pow(lrp,6.08),0.0,0.50) );
	
  }